﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;

namespace Jarvis.Rules
{
    [Serializable()]
    public class Rule : ISerializable
    {
        public String Name { get; set; }
        public String ContextElement { get; set; }
        public String Outcome { get; set; }

        public Boolean And { get; set; }
        public ObservableCollection<RuleComponent> Components { get; set; }

        public Rule()
        {
            this.Components = new ObservableCollection<RuleComponent>();

            this.Name = "New Rule";
            this.Outcome = "Unknown";
            this.ContextElement = "Activity";

            RuleComponent c = new RuleComponent();
            c.Field = "Bar";
            c.Operation = RuleComponent.NotEqual;
            c.Value = "Foo";

            this.Components.Add(c);
        }

        public Rule(SerializationInfo info, StreamingContext ctxt)
        {
            this.Name = (String)info.GetValue("Name", typeof(String));
            this.ContextElement = (String)info.GetValue("ContextElement", typeof(String));
            this.Outcome = (String)info.GetValue("Outcome", typeof(String));
            this.And = (Boolean)info.GetValue("And", typeof(Boolean));
            this.Components = (ObservableCollection<RuleComponent>)info.GetValue("Components", typeof(ObservableCollection<RuleComponent>));
        }
        
        public void GetObjectData(SerializationInfo info, StreamingContext ctxt)
        {
            info.AddValue("Name", this.Name);
            info.AddValue("ContextElement", this.ContextElement);
            info.AddValue("Outcome", this.Outcome);
            info.AddValue("And", this.And);
            info.AddValue("Components", this.Components);
        }

        public Boolean EvaluateState(Dictionary<String, object> state)
        {
            if (Components == null)
                Components = new ObservableCollection<RuleComponent>();

            foreach (RuleComponent component in Components)
            {
                Boolean match = component.IsMatch(state);

                if (!match && And)
                    return false;
                else if (match && !And)
                    return true;
            }

            if (Components.Count > 0 && And)
                return true;

            return false;
        }
    }
}
